#ifndef svl_TNode_H
#define svl_TNode_H

/**********
#include <TypeInfo.h>
#include <string>
#include <stdlib.h>
//#include <cstringt.h>
#include <comutil.h>
#include <stdio.h>
//#include <atltime.h>
#include <atlcomtime.h>

//#include <atlbase.h>
//#include <atlwin.h>
#include "svl_TWindow.h"

#pragma warning(disable : 4355)
#pragma warning(disable : 4996)
    
#define svl_Except void Except(char *S)\
  {svl::TExcept(svl::TString() << typeid(*this).name() << "::" << S).Throw();}

#define svl_ClassName(V) typeid(V).name()
****************/

#include "svl.h"

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

namespace svl
{

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
  
template<class T> struct TNode;  
template<class T> struct TNodeArray : public TDebug
{
  void Clear() { a.Clear();}
  int  Count() { return a.Numb();}
  //
  T      &Get(int N) { return *(T*)a.Get(N);}
  int    GetN(T  *W) { return a.GetN(W);}
  bool Search(T  *W) { return a.Search(W);}
  bool Search(T  *W,int &outN) { return a.Search(W,outN);}
  //
  void SetEnDelete(T  *P,bool EnDelete) { a.SetEnDelete(P,EnDelete);}
  void SetEnDelete(int N,bool EnDelete) { a.SetEnDelete(N,EnDelete);}
  bool GetEnDelete(T  *P)               { return a.GetEnDelete(P);}

private:
  void AddFirst(T *Add,bool EnDelete) { a.InsertUp(0,Add,EnDelete);}
  void AddLast (T *Add,bool EnDelete) { a.Add(Add,EnDelete);}
  //
  void AddBefore(T *Add,T *Cur,bool EnDelete) { a.InsertUp(GetN(Cur),Add,EnDelete);}
  void AddAfter (T *Add,T *Cur,bool EnDelete) { a.InsertDn(GetN(Cur),Add,EnDelete);}
  //
  void Delete(int N) { a.Delete(N);}
  void Delete(T  *P) { a.Delete(P);}

  svl::TArray a;
  friend TNode<T>;
};

////////////////////////////////////////////////////////////////////////////////

template<class T> struct TNode : public svl::TArray_Object
{
  struct TType { virtual TType &Type() { static TType T; return T;} };
  virtual TType &Type() { return TType().Type();}
  //virtual char *ClassName() { return (char*)typeid(*this).name();}

  //
  TNode(TNodeArray<T> &Children,T *Parent = NULL,bool EnDelete = false) : children(Children)
  {
    parent = Parent; if (parent) { parent->Children_AddLast((T*)this,EnDelete);}
  }                                                    
  //TNode(TNodeArray<T> &Children) : children(Children) { parent = NULL;}
 ~TNode()
  {
    Children_Delete(); if (parent) 
    { 
      int N; if (parent->Children().Search((T*)this,N)) 
        { parent->Children().SetEnDelete(N,false); parent->Children_Delete(N);}
    }
  }
  //
  void SetEnDelete(bool V) { if (parent) { Parent()->Children().SetEnDelete((T*)this,V);} }
  bool GetEnDelete()       { return parent ? Parent()->Children().GetEnDelete((T*)this) : false;}
  //
  T             *Parent()   { return parent;}
  TNodeArray<T> &Children() { return children;}
  //
  virtual void Children_AddFirst(T *Add,bool EnDelete = true) { Children().AddFirst(Add,EnDelete);}
  virtual void Children_AddLast (T *Add,bool EnDelete = true) { Children().AddLast (Add,EnDelete);}
  //
  virtual void Children_AddBefore(T *Add,T *Cur,bool EnDelete = true) { Children().AddBefore(Add,Cur,EnDelete);}
  virtual void Children_AddAfter (T *Add,T *Cur,bool EnDelete = true) { Children().AddAfter (Add,Cur,EnDelete);}
  //
  virtual void Children_Delete()      { while (Children().Count()) { Children_Delete(0);} }
  virtual void Children_Delete(int N) { Children_Delete(&Children().Get(N));}
  virtual void Children_Delete(T  *P) { P->Children_Delete(); int N; if (Children().Search(P,N)) { Children().Delete(N);} }
  //
  T *SearchThisOrParent(const TType &Type)
  {
    T *P = static_cast<T*>(this); while (P)
    {
      if (&((TType&)Type).Type() == &P->Type())
        { return P;}
      P = P->Parent();
    }
    return NULL;
  }
  
private:
  T             *parent;  
  TNodeArray<T> &children;
};

////////////////////////////////////////////////////////////////////////////////
}

#endif
